package pro.shushi.pamirs.hr.core.action;

import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Component;
import pro.shushi.pamirs.framework.connectors.data.sql.Pops;
import pro.shushi.pamirs.framework.connectors.data.sql.query.QueryWrapper;
import pro.shushi.pamirs.hr.api.model.org.Employee;
import pro.shushi.pamirs.hr.api.model.org.Position;
import pro.shushi.pamirs.hr.api.pmodel.DepartmentProxy;
import pro.shushi.pamirs.meta.annotation.Function;
import pro.shushi.pamirs.meta.annotation.Model;
import pro.shushi.pamirs.meta.api.dto.condition.Pagination;
import pro.shushi.pamirs.meta.api.dto.wrapper.IWrapper;
import pro.shushi.pamirs.meta.common.lambda.LambdaUtil;
import pro.shushi.pamirs.meta.common.util.ListUtils;
import pro.shushi.pamirs.meta.constant.FunctionConstants;
import pro.shushi.pamirs.meta.enmu.FunctionOpenEnum;
import pro.shushi.pamirs.meta.enmu.FunctionTypeEnum;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Component
@Model.model(DepartmentProxy.MODEL_MODEL)
public class DepartmentProxyAction {

    /**
     * 搜索条件中有岗位名称，模拟根据岗位名称查询部门（且岗位名称和部门不在一张表中, 但需要存在关联关系）
     *
     * 非存储字段搜索：https://doc.oinone.top/dai-ma-shi-jian/5592.html
     * @param page
     * @param queryWrapper
     * @return
     */
    @Function.Advanced(type = FunctionTypeEnum.QUERY, displayName = "查询列表")
    @Function.fun(FunctionConstants.queryPage)
    @Function(openLevel = {FunctionOpenEnum.API})
    public Pagination<DepartmentProxy> queryPage(Pagination<DepartmentProxy> page, QueryWrapper<DepartmentProxy> queryWrapper) {
        // 通过LambdaUtil方式字段
        String positionNameField = LambdaUtil.fetchFieldName(DepartmentProxy::getPositionName);
        // 非存储字段前端在发起请求拼接查询条件都放在QueryData中
        Map<String, Object> queryData = queryWrapper.getQueryData();
        if (queryData != null && queryData.get(positionNameField) != null) {
            String positionName = (String) queryData.get(positionNameField);
            // 根据自定义拼接条件查询数据，参考：https://doc.oinone.top/backend/11467.html
            List<Position> positions = new Position().queryList(Pops.<Position>lambdaQuery()
                    .from(Position.MODEL_MODEL).like(Position::getName, positionName));
            if (CollectionUtils.isNotEmpty(positions)) {
                List<String> deptCodes = ListUtils.transform(positions, Position::getDepartmentCode);
                queryWrapper.lambda().in(DepartmentProxy::getCode, deptCodes);
            } else {
                return page;
            }
        }
        page = new DepartmentProxy().queryPage(page, queryWrapper);
        computeDeptStaffCount(page);

        return page;
    }

    /***
     * 补充部门人员，实时获取
     * @param page
     */
    private void computeDeptStaffCount(Pagination<DepartmentProxy> page) {
        List<DepartmentProxy> content = page.getContent();
        if (CollectionUtils.isNotEmpty(content)) {
            List<String> deptCodes = ListUtils.transform(content, DepartmentProxy::getCode);
            Map<String, Long> employeeCountMap = queryDbEmployeeCount(deptCodes);
            content.forEach(dept -> {
                dept.setStaffCount(employeeCountMap.getOrDefault(dept.getCode(),0L));
            });
        }
    }

    private Map<String/**部门编码*/, Long/**部门人数*/> queryDbEmployeeCount(List<String> deptCodes) {
        Map<String, Long> employeeCountMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(deptCodes)) {
            IWrapper<Employee> qw = Pops.<Employee>lambdaQuery().from(Employee.MODEL_MODEL).setSortable(Boolean.FALSE).setBatchSize(-1)
                    .select(Employee::getCode, Employee::getDepartmentCode)
                    .in(Employee::getDepartmentCode, deptCodes);
            List<Employee> employees = new Employee().queryList(qw);
            if (CollectionUtils.isNotEmpty(employees)) {
                employeeCountMap = employees.stream().collect(Collectors.groupingBy(Employee::getDepartmentCode, Collectors.counting()));
            }
        }

        return employeeCountMap;
    }

}
